package pathFinderPackage;

import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import mapPackage.IDTroncon;
import mapPackage.ITroncon;
import mapPackage.IVille;
import mapPackage.MapException;
import preferencePackage.Preference;
import xmlPackage.Carte;

public class Itineraire 
{
	private Vector<IDTroncon> troncons ;
	private String VilleDepart 	;
	private String VilleArrivee ;
	private float score;
	
	public Itineraire()
	{
		troncons = new Vector<IDTroncon>();
	}
	
	public int getLongueurParcour()
	{
		int longueur = 0 ;
		
		try 
		{
			
			for( IDTroncon id : this.troncons )
			{
				ITroncon t = Carte.GetInstance().getTroncon(id);
				longueur += t.getLongueur() ;
			}
		
		}
		catch (MapException e) {e.printStackTrace();}
		
		return longueur;
	}
	
	public float getTempsParcour()
	{
		float temps = 0 ;
		
		try 
		{
			for( IDTroncon id : this.troncons )
			{
				ITroncon t = Carte.GetInstance().getTroncon(id);
				temps += (  t.getLongueur() / t.getVitesseMax()  );
			}
		}
		catch (MapException e) {e.printStackTrace();}
		
		return temps;
	}
	
	public String getVilleDepart() 
	{
		return VilleDepart;
	}
	
	public void setVilleDepart(String villeDepart) 
	{
		VilleDepart = villeDepart;
	}
	
	public String getVilleArrivee() 
	{
		return VilleArrivee;
	}
	
	public Vector<IDTroncon> getTroncons() {
		return troncons;
	}

	public void setVilleArrivee(String villeArrivee) 
	{
		VilleArrivee = villeArrivee;
	}
	
	public void ajouterTroncon(IDTroncon t , int index )
	{
		this.troncons.add(index, t);
	}

	public boolean contientVille(String ville)
	{
		try 
		{
			for( IDTroncon t : this.troncons )
			{
				if ( Carte.GetInstance().getTroncon(t).getVille1().equals(ville) ) return true;
				if ( Carte.GetInstance().getTroncon(t).getVille2().equals(ville) ) return true;
			}
		}
		catch (MapException e){e.printStackTrace();}
		return false;
	}
	
	public boolean contientTroncon(IDTroncon troncon)
	{

		for( IDTroncon t : this.troncons )
		{
			if ( t == troncon ) return true;
		}
		return false;
	}
	
	public boolean contientVille(String ville, int fromEtape)
	{
		try 
		{
			int cpt = 0;
			for( IDTroncon t : this.troncons )
			{
				if (cpt > fromEtape + 1)
				{
					if ( Carte.GetInstance().getTroncon(t).getVille1().equals(ville) ) return true;
					if ( Carte.GetInstance().getTroncon(t).getVille2().equals(ville) ) return true;
				}
				++cpt;
			}
		}
		catch (MapException e){e.printStackTrace();}
		return false;
	}
	
	public boolean contientTroncon(IDTroncon troncon , int fromEtape)
	{
		int cpt = 0;
		for( IDTroncon t : this.troncons )
		{
			if (cpt > fromEtape)
			{
				if ( t == troncon ) return true;
			}
			++cpt;
		}
		return false;
	}
	
	public Itineraire clone()
	{
		Itineraire clone = new Itineraire();
		
		for( IDTroncon t : this.troncons )
		{
			clone.troncons.add(t);
		}
		
		clone.VilleArrivee = this.VilleArrivee ;
		clone.VilleDepart = this.VilleDepart ;
		clone.score = this.score;
		return clone;
	}
	
	public String toString()
	{
		String s ="depart="+VilleDepart ;
		
 
		for( IDTroncon t : this.troncons )
		{
			try {
				s+="\n\t"+ Carte.GetInstance().getTroncon(t) ;
			} catch (MapException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		s+= "\narrivee="+VilleArrivee ;
			
		return s;
	}
	
	
	public void ItineraireRetour()
	{
		
		String tmp		= this.VilleArrivee;
		VilleArrivee	= VilleDepart ;
		VilleDepart		= tmp;
		
		
		Vector<IDTroncon> nouvelle = new Vector<IDTroncon>();
		for(IDTroncon t : this.troncons)
		{
			nouvelle.add(0,t);
		}
		
		this.troncons.clear();
		this.troncons = nouvelle;
		
	}
	
	public void fusionnerAvec( Itineraire it) 
	{
		try 
		{
			if(it.getVilleArrivee() == null)throw new Exception("impossible de fusionner : l'itineraire a ville Arrive null");
			if(it.getVilleDepart() == null) throw new Exception("impossible de fusionner : l'itineraire a ville Depart null");
			if(this.VilleArrivee == null) throw new Exception("impossible de fusionner : j'ai ville arrivee null");
			if(this.VilleDepart == null) throw new Exception("impossible de fusionner : j'ai a ville Depart null");
			
			if( this.VilleDepart == it.VilleArrivee )
			{
				Vector<IDTroncon> nouvelle = new Vector<IDTroncon>(it.troncons) ;
				for(IDTroncon t : this.troncons)
				{
					nouvelle.add(t);
				}
				this.troncons.clear();this.troncons = nouvelle;
				this.VilleDepart = it.VilleDepart;
			}
			else
			{
				if( this.VilleArrivee == it.VilleDepart  )
				{
					for(IDTroncon t : it.troncons)
					{
						this.troncons.add(t);
					}
					this.VilleArrivee = it.VilleArrivee;
				}
				else
				{
					throw new Exception("impossible de fusionner les 2 itineraires : \nthis.va="+this.VilleArrivee +"\nthis.vd="+this.VilleDepart +"\nit.va="+it.VilleArrivee +"\nit.vd="+it.VilleDepart );
				}
			}
		}
		catch (Exception e) {e.printStackTrace();}
	}
	
	public float getScore() {
		return score;
	}

	public float setScore( List<Preference> prefs )
	{
		try 
		{
			score = 0 ;

			IVille ville = Carte.GetInstance().getVille( this.getVilleDepart() ) ;
			// on evalue selon toutes les preferences :
			for( Preference p : prefs )
			{
				float s = 0 ;
				for( IDTroncon ts :  this.getTroncons() )
				{
					ITroncon to = Carte.GetInstance().getTroncon(ts) ;
					score += ( p.evaluerDestination(ville, to) * p.getClassement() ) ;
					s = ( p.evaluerDestination(ville, to) * p.getClassement() ) ;
				};
				
			}	
			return score;
		}
		catch (MapException e) {e.printStackTrace();}
		return 0;
	}
}
